﻿namespace ScrumLite.WebUx.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using ScrumLite.Services;
    using ScrumLite.Services.Contracts;
    using System.Globalization;

    public class MockReviewsService : IReviewsService
    {
        public bool AddReviewCalled { get; set; }
        public bool UpdateReviewCalled { get; set; }
        public bool GetReviewsCalled { get; set; }
        public bool GetReviewsByWeekCalled { get; set; }
        public Review ReviewAdded { get; set; }
        public Review ReviewUpdated { get; set; }
        
        public const string ProjectIdForEmptyData = "13c659fb-fa13-4343-ba36-1af8b48eee97";

        private static List<Review> reviews ;

        static MockReviewsService()
        {
            InitializeData();
        }

        public static void InitializeData()
        {
            reviews = new List<Review>();
            reviews.Add(new Review { Id = Guid.NewGuid(), ProjectId = new Guid("AF06A611-12CE-4C06-B3AD-E2754D12D516"), OccurredOn = DateTime.Parse("2008-02-01", CultureInfo.CurrentCulture), ConductedBy = "southy", EvidenceUrl = "http://svnrepo.scrumlite.org/ScrumLite-v1/process/review/Review-" + DateTime.Now.ToString("yyyy-MM-dd",CultureInfo.InvariantCulture) + ".docx" });
            reviews.Add(new Review { Id = Guid.NewGuid(), ProjectId = new Guid("AF06A611-12CE-4C06-B3AD-E2754D12D516"), OccurredOn = DateTime.Parse("2008-02-01", CultureInfo.CurrentCulture).Subtract(TimeSpan.FromDays(1)), ConductedBy = "southy", EvidenceUrl = "http://svnrepo.scrumlite.org/ScrumLite-v1/process/review/Review-" + DateTime.Now.Subtract(TimeSpan.FromDays(1)).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + ".docx" });
            reviews.Add(new Review { Id = Guid.NewGuid(), ProjectId = new Guid("AF06A611-12CE-4C06-B3AD-E2754D12D516"), OccurredOn = DateTime.Parse("2008-02-01", CultureInfo.CurrentCulture).Subtract(TimeSpan.FromDays(7)), ConductedBy = "southy", EvidenceUrl = "http://svnrepo.scrumlite.org/ScrumLite-v1/process/review/Review-" + DateTime.Now.Subtract(TimeSpan.FromDays(2)).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + ".docx" });
        }

        public Review[] GetReviews(string projectId)
        {
            GetReviewsCalled = true;
            var selectedReviews = (from r in reviews
                                  where r.ProjectId == new Guid(projectId)
                                  orderby r.OccurredOn descending 
                                  select r).ToArray();

            return selectedReviews;
        }

        public Dictionary<int, int> GetReviewsByWeek(string projectId)
        {
            GetReviewsByWeekCalled = true;

            var groupedReviews = from r in reviews
                                 where r.ProjectId == new Guid(projectId)
                                 group r by GetYearWeek(r.OccurredOn) into Weekly
                                 orderby Weekly.Key
                                 select new
                                 {
                                     Week = Weekly.Key,
                                     Count = Weekly.Count()
                                 };
            return groupedReviews.ToDictionary(k => k.Week, v => v.Count);
        }

        private static int GetYearWeek(DateTime date)
        {
            CultureInfo invariant = CultureInfo.InvariantCulture;
            return invariant.Calendar.GetWeekOfYear(date,
                                   invariant.DateTimeFormat.CalendarWeekRule,
                                   invariant.DateTimeFormat.FirstDayOfWeek);
        }

        public Review GetReview(string reviewId)
        {
            var review = (from r in reviews
                           where r.Id == new Guid(reviewId)
                           select r).SingleOrDefault();

            return review;
        }

        public void AddReview(Review review)
        {
            review.Id = Guid.NewGuid();
            this.AddReviewCalled = true;
            this.ReviewAdded = review;
            reviews.Add(review);
        }

        public void UpdateReview(Review review)
        {
            this.UpdateReviewCalled = true;
            this.ReviewUpdated = review;
            foreach (Review r in reviews)
            {
                if (r.Id == review.Id)
                {
                    reviews.Remove(r);
                    break;
                }
            }
            reviews.Add(review);
        }
    }
}
